<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>PlayIntegrityFork Controls</title>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<style>
/*glow, blur, animations */
:root{
  --bg:#1f2233; --fg:#e6e6e6; --accent:#1592FF;
  --panel-bg:#232637D9; --card-bg:#232637E6;
  --border-radius:14px; --shadow: rgba(0,0,0,0.5);
  --transition:0.3s;
}
*{box-sizing:border-box}
body{
  margin:0;min-height:100vh;
  display:flex;align-items:center;justify-content:center;
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,system-ui;
  background:linear-gradient(135deg,#1f2233,#14172b);
  color:var(--fg);
  -webkit-font-smoothing:antialiased;
}
.card{
  width:360px; max-width:94%;
  background:var(--panel-bg);
  border-radius:var(--border-radius);
  padding:22px;
  box-shadow:0 18px 48px var(--shadow);
  position:relative; overflow:hidden;
  transform: translateY(0);
  transition: transform .35s ease, box-shadow .35s ease;
}
.card::before{
  content:"";
  position:absolute; inset:0;
  background:radial-gradient(circle,var(--accent) 0%, transparent 60%);
  filter:blur(14px); opacity:.14; pointer-events:none; z-index:0;
  animation: cardGlow 10s ease-in-out infinite;
}
@keyframes cardGlow{0%,100%{opacity:.12}50%{opacity:.28}}
h1{position:relative;z-index:2;margin:0 0 12px 0;text-align:center;font-size:18px;color:var(--accent)}
.row{
  position:relative; z-index:2;
  display:flex;align-items:center;justify-content:space-between;
  gap:10px;padding:12px 6px;border-radius:10px;
  transition:background var(--transition), transform var(--transition);
}
.row + .row { margin-top:6px; }
.row:hover{ transform: translateY(-4px); box-shadow:0 10px 28px rgba(0,0,0,0.35); }

/* switch */
.switch{position:relative;width:56px;height:32px;flex-shrink:0}
.switch input{position:absolute;opacity:0;width:0;height:0}
.slider{position:absolute;inset:0;border-radius:999px;background:#2f3138;transition:background var(--transition), box-shadow var(--transition)}
.knob{position:absolute;left:4px;top:4px;width:24px;height:24px;border-radius:50%;background:#fff;transition:transform .22s cubic-bezier(.2,.9,.2,1);}
.switch input:checked + .slider{background:var(--accent); box-shadow:0 6px 24px rgba(21,146,255,0.18)}
.switch input:checked + .slider .knob{transform:translateX(24px)}

/* disabled look */
.switch input:disabled + .slider{ background: rgba(255,255,255,0.06); box-shadow:none; cursor:not-allowed; }
.switch input:disabled + .slider .knob{ background: rgba(255,255,255,0.65); }

/* inline note */
.warning-line{
  margin-top:12px;padding:10px;border-radius:10px;
  background: linear-gradient(90deg, rgba(255,120,120,0.06), rgba(255,120,120,0.02));
  color:#ffb3b3;font-weight:600;font-size:13px;text-align:center;
  display:none;
  box-shadow:0 6px 20px rgba(0,0,0,0.25);
}

/* toast */
.toast{
  position:fixed;left:50%;bottom:22px;transform:translateX(-50%) translateY(20px);
  background:linear-gradient(90deg,#12c48b,#0aa1ff);color:#fff;padding:10px 16px;border-radius:999px;
  box-shadow:0 10px 30px rgba(0,0,0,0.45);opacity:0;pointer-events:none;transition:transform .36s ease,opacity .36s ease;z-index:9999;font-weight:700;
}
.toast.show{opacity:1;pointer-events:auto;transform:translateX(-50%) translateY(0);}

/* helper */
.input-label {display:flex;align-items:center;gap:8px;font-weight:700}
.keyname {font-size:12px;color:rgba(255,255,255,0.65)}
.footer {margin-top:14px;text-align:center;color:rgba(255,255,255,0.45);font-size:12px}

/* responsive */
@media(max-width:420px){ .card{width:92%;padding:18px} .switch{width:52px;height:30px} .switch input:checked + .slider .knob{transform:translateX(22px)} }
</style>
</head>
<body>
  <div class="card" role="region" aria-label="Play Integrity Fork Controls">
    <h1><span class="material-icons" style="vertical-align:middle;font-size:18px;margin-right:6px">android</span> Play Integrity Fork Controls</h1>

    <div id="warningLine" class="warning-line" role="alert"></div>

    <div id="rows" aria-live="polite">
      <div class="row"><div class="input-label"><span class="material-icons">build</span> <div>Spoof Build <div class="keyname">spoofBuild</div></div></div>
        <label class="switch"><input id="spoofBuild" type="checkbox"><span class="slider"><span class="knob"></span></span></label></div>

      <div class="row"><div class="input-label"><span class="material-icons">public</span> <div>Spoof Props <div class="keyname">spoofProps</div></div></div>
        <label class="switch"><input id="spoofProps" type="checkbox"><span class="slider"><span class="knob"></span></span></label></div>

      <div class="row"><div class="input-label"><span class="material-icons">settings_ethernet</span> <div>Force Strong <div class="keyname">spoofProvider</div></div></div>
        <label class="switch"><input id="spoofProvider" type="checkbox"><span class="slider"><span class="knob"></span></span></label></div>

      <div class="row"><div class="input-label"><span class="material-icons">vpn_key</span> <div>Spoof Signature <div class="keyname">spoofSignature</div></div></div>
        <label class="switch"><input id="spoofSignature" type="checkbox"><span class="slider"><span class="knob"></span></span></label></div>

      <div class="row"><div class="input-label"><span class="material-icons">fingerprint</span> <div>Spoof Fingerprint <div class="keyname">spoofVendingFinger</div></div></div>
        <label class="switch"><input id="spoofVendingFinger" type="checkbox"><span class="slider"><span class="knob"></span></span></label></div>

      <div class="row"><div class="input-label"><span class="material-icons">storefront</span> <div>Spoof to A12 <div class="keyname">spoofVendingSdk</div></div></div>
        <label class="switch"><input id="spoofVendingSdk" type="checkbox"><span class="slider"><span class="knob"></span></span></label></div>

      <div class="row"><div class="input-label"><span class="material-icons">bug_report</span> <div>Generate Logs <div class="keyname">verboseLogs</div></div></div>
        <label class="switch"><input id="verboseLogs" type="checkbox"><span class="slider"><span class="knob"></span></span></label></div>
    </div>

    <div class="footer">IntegrityBox • 2025</div>
  </div>

  <div id="toast" class="toast" role="status" aria-live="polite">Done ✅</div>

<script>
const PROP_CANDIDATES = [
  "/data/adb/modules/playintegrityfix/custom.pif.prop",
  "/data/adb/custom.pif.prop"
];

const KEYS = ["spoofBuild","spoofProps","spoofProvider","spoofSignature","spoofVendingFinger","spoofVendingSdk","verboseLogs"];

/* helper for UI */
const toastEl = document.getElementById('toast');
function showToast(msg, timeout=1400){
  toastEl.textContent = msg;
  toastEl.classList.add('show');
  setTimeout(()=>toastEl.classList.remove('show'), timeout);
}
function showWarning(text){
  const w = document.getElementById('warningLine');
  if(!text){ w.style.display='none'; w.textContent=''; return; }
  w.style.display='block'; w.textContent = text;
}

/* execute shell and return trimmed stdout as string */
async function sh(cmd){
  try{
    if(typeof ksu?.exec === 'function'){
      const maybe = ksu.exec(cmd);
      if(maybe && typeof maybe.then === 'function') return (await maybe).toString().trim();
      if(typeof maybe === 'string') return maybe.toString().trim();
      return await new Promise((resolve, reject) => {
        const cb = `cb_${Date.now()}_${Math.random()*10000|0}`;
        window[cb] = (code, stdout, stderr) => {
          try{ delete window[cb]; }catch(e){}
          if(code === 0) resolve((stdout||'').toString().trim());
          else resolve(((stdout||'') + (stderr||'')).toString().trim());
        };
        try{
          ksu.exec(cmd, "{}", cb);
        }catch(e){
          resolve('');
        }
      });
    } else {
      return '';
    }
  }catch(e){
    return '';
  }
}

/* find the first existing prop file */
async function findPropFile(){
  for(const p of PROP_CANDIDATES){
    const out = await sh(`sh -c 'if [ -f "${p}" ]; then echo found; else echo missing; fi'`);
    if(out.trim() === 'found') return p;
  }
  return null;
}

/* check advanced settings presence */
async function hasAdvancedSettings(file){
  if(!file) return false;
  const out = await sh(`sh -c 'grep -q \"^spoofProvider=\" \"${file}\" && echo 1 || echo 0'`);
  return out.trim() === '1';
}

/* read key value */
async function readKey(file, key){
  if(!file) return '';
  const cmd = `sh -c 'grep -m1 \"^${key}=\" \"${file}\" | cut -d\"=\" -f2- || echo \"\"'`;
  const out = await sh(cmd);
  return (out ?? '').toString().trim();
}

/* write key value: if exists replace, else append */
async function writeKey(file, key, value){
  if(!file) return false;
  const cmd = `sh -c 'if grep -q \"^${key}=\" \"${file}\"; then sed -i \"s/^${key}=.*/${key}=${value}/\" \"${file}\"; else printf \"\\n${key}=${value}\\n\" >> \"${file}\"; fi'`;
  await sh(cmd);
  return true;
}

/* restart GMS */
async function restartGMS(){
  await sh(`sh -c 'am force-stop com.google.android.gms.unstable 2>/dev/null || true; am force-stop com.android.vending 2>/dev/null || true'`);
}

/* set toggles from file */
async function init(){
  const file = await findPropFile();
  if(!file){
    showWarning("⚠️ Fingerprint not found. Kindly click on PlayIntegrityFork module's action button");
    // disable all toggles visually
    KEYS.forEach(k => {
      const el = document.getElementById(k);
      if(el) { el.disabled = true; el.checked = false; }
    });
    return;
  }

  const adv = await hasAdvancedSettings(file);
  if(!adv){
    showWarning("⚠️ Advanced Settings not detected. Enable PIF Advanced toggle & click on action button");
    KEYS.forEach(k => {
      const el = document.getElementById(k);
      if(el) { el.disabled = true; el.checked = false; }
      const parent = document.getElementById(k)?.closest('.row');
      if(parent) parent.title = "Advanced Settings missing, 'spoofProvider is unavailable";
    });
    return;
  }

  // Hide warning if advanced settings exist
  showWarning('');

  // For each key, read its value and set toggle
  for(const key of KEYS){
    const el = document.getElementById(key);
    if(!el) continue;
    el.disabled = false;
    const val = await readKey(file, key);
    // treat "1" as enabled, "100" as enabled (for verboseLogs), everything else disabled
    el.checked = (val === '1' || val === '100');
    el.addEventListener('change', async (ev) => {
      el.parentElement.animate([{ transform: 'scale(1)' }, { transform: 'scale(1.03)' }, { transform: 'scale(1)' }], { duration: 240, easing: 'ease' });
      const newVal = (key === 'verboseLogs') ? (el.checked ? '100' : '0') : (el.checked ? '1' : '0');
      await writeKey(file, key, newVal);
      await restartGMS();
      try { localStorage.setItem(`toggle_${key}`, newVal); } catch(e){}
      showToast('Done ✅');
    }, { passive:true });
  }
}

/* DOM loaded */
document.addEventListener('DOMContentLoaded', ()=>{ init().catch(e=>{ console.error(e); showWarning("⚠️ Initialization Failed check KSU is available."); }) });
</script>
</body>
</html>
